home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 03 - 1987 / 03.07 Jul 87 / pop up source / PaletteSample.p < prev    next >
Encoding:
Text File  |  1986-12-18  |  10.6 KB  |  420 lines  |  [TEXT/MPS ]

  1. program PSample;
  2. {Compiler Switch Settings}
  3. {$R+}  {range checking on}
  4. {$OV+} {overflow checking on}
  5.  
  6. uses  
  7.       {$U MemTypes.p } MemTypes,
  8.       {$U QuickDraw.p} QuickDraw,
  9.       {$U OsIntf.p   } OsIntf,
  10.       {$U ToolIntf.p } ToolIntf,
  11.       {$U UPalette.p } UPalette;
  12.  
  13. const
  14.  AppleID = 1; {Menu ID for Apple menu}
  15.  AboutItem = 1;{Item number for About... command}
  16.  
  17.  FileID = 2;       {Menu ID for File menu}
  18.  NewWindowItem = 1;{Item number for New window command}
  19.  QuitItem = 2;     {Item number for Quit command}
  20.  
  21.  MenuBarHeight = 21;
  22.  
  23. type
  24.     PatRecord = record
  25.         number: integer;
  26.         thePattern: Pattern;
  27.     end;
  28.     
  29.     PatRecPtr = ^PatRecord;
  30.     PatRecHandle = ^PatRecPtr;
  31.     
  32. var
  33.  AppleMenu : MenuHandle;
  34.  FileMenu  : MenuHandle;
  35.  
  36.  theWindow : windowPtr; { the current front window }
  37.  oldPort   : GrafPtr;   { temporary grafport info }
  38.  theEvent  : EventRecord;
  39.  
  40.  systemPatterns : PatHandle; { handle to standard pattern list }
  41.  
  42.  currentPattern : Pattern; { new windows get this pattern }
  43.  programDone    : Boolean; { true if Quit is selected }
  44.  nextWindow     : Point;   { governs placement of new windows }
  45.     currentPatNum : integer;
  46. {---------------------------}
  47.  
  48.  
  49. procedure SetUpMenus;
  50. var 
  51.  { we need this cause the 'Apple'
  52.   character isn't on the keyboard }
  53.  appleTitle: String[1];
  54.  
  55. begin {SetUpMenus}
  56.  
  57.  { create Apple menu }
  58.  appleTitle := ' ';
  59.  appleTitle[1] := chr( appleMark );
  60.  AppleMenu := NewMenu( AppleID,appleTitle );
  61.  AppendMenu( AppleMenu, 'Sorry, just for looks…;(-' );
  62.  InsertMenu( AppleMenu, 0 );
  63.  
  64.  { create File menu }
  65.  FileMenu := NewMenu( FileID,'File' );
  66.  AppendMenu( FileMenu,'New Window' );
  67.  AppendMenu( FileMenu,'Quit' );
  68.  InsertMenu( FileMenu, 0 );
  69.  
  70.  { put it up on the screen }        
  71.  DrawMenuBar;
  72.  
  73. end;  {SetUpMenus}
  74.  
  75. procedure MakeNewWindow;
  76.  { Create a new window }
  77. var
  78.  r : Rect; { used for window size }
  79.  aWindow : WindowPtr; { NewWindow returns a WindowPtr... }
  80.  
  81. begin
  82.   { use 1/4 screen space for rectangle }
  83.  with ScreenBits.bounds do
  84.   begin
  85.    r.top   := top + MenuBarHeight;{ ignore menu bar... }
  86.    r.left  := left;
  87.    r.bottom:= bottom div 2;
  88.    r.right := right div 2;
  89.   end;
  90.  
  91.  { offset placement of this window }
  92.  nextWindow.v := nextWindow.v + 20;
  93.  nextWindow.h := nextWindow.h + 20;
  94.  
  95.  { too far down? }
  96.  if ( nextWindow.v + 20 > ScreenBits.bounds.bottom)
  97.   then nextWindow.v := 20;
  98.  
  99.  { too far over? }
  100.  if ( nextWindow.h + 20 > ScreenBits.bounds.right)
  101.   then nextWindow.h := 20;
  102.  
  103.  { place the rect }
  104.  OffSetRect( r, nextWindow.h , nextWindow.v );
  105.  
  106.  { create the window }
  107.  aWindow := NewWindow( nil, r, 'Another Window',
  108.             true, documentProc, pointer(-1), true,
  109.             longint(0) );
  110.  SetPort( aWindow );
  111.  
  112.  { force an update event for this window }
  113.  InvalRect( thePort^.portRect );
  114.  
  115.  { create storage space for a pattern, and set it }
  116.  WindowPeek( aWindow )^.refCon := 
  117.        longint( NewHandle( SizeOf( PatRecord ) ) );
  118.  PatRecHandle( WindowPeek( aWindow )^.refCon )^^.thePattern := currentPattern;
  119.     PatRecHandle( WindowPeek( aWindow )^.refCon )^^.number := currentPatNum;
  120.  
  121. end; {MakeNewWindow}
  122.  
  123.  
  124. procedure DestroyWindow( whichOne : WindowPtr );
  125.  { We can't just do a DisposeWindow, because we are
  126.   maintaining an extra block on the heap that contains
  127.   the current pattern for each window.    We have to dispose
  128.   of the block ourselves, because the WM doesn't know it's
  129.   there.}
  130. begin
  131.  DisposHandle( handle( WindowPeek( whichOne )^.refCon ) );
  132.  DisposeWindow( whichOne );
  133. end; {DestroyWindow}
  134.  
  135. procedure DoMenuClick;
  136. {  Handle mouse-down event in menu bar.  }
  137. var
  138.  menuChoice : longint; { returned by MenuSelect }
  139.  theMenu : integer;  { ID of selected menu }
  140.  theItem : integer;  { number of selected item }
  141.  
  142. begin
  143.  menuChoice := MenuSelect( theEvent.where );
  144.  
  145.  { valid selection only if non-zero }
  146.  if menuChoice <> 0 then
  147.   begin
  148.    theMenu := HiWord( menuChoice );
  149.    theItem := LoWord( menuChoice );
  150.  
  151.    case theMenu of
  152.     AppleID: { don't really do anything };
  153.  
  154.     { if they pick Quit, set global flag.
  155.      if they pick New Window, go make one }
  156.     FileID:  if theItem = QuitItem
  157.              then programDone := true
  158.              else if theItem = NewWindowItem
  159.                   then MakeNewWindow;
  160.  
  161.    end;{ case theMenu… }
  162.  
  163.    { Unhighlight menu title }
  164.    HiliteMenu( 0 );
  165.  
  166.   end; { if menuChoice… }
  167.  
  168. end;{DoMenuClick}
  169.  
  170. procedure DoInContent;
  171. { handle mouseclicks in a window }
  172. var
  173.  tempPatNum : integer; { temporary pattern number }
  174. begin
  175.  
  176.  { this avoids inverting the "current selection"
  177.   when popping-up the pattern }
  178.  tempPatNum:=PatRecHandle( WindowPeek( theWindow )^.refCon )^^.number;
  179.  
  180.  { pop-up the palette, and let them select a pattern }
  181.  PatternSelect( tempPatNum, theEvent.where );
  182.  
  183.  { a selection has been made only if tempPatNum has changed }
  184.  if tempPatNum<>currentPatNum then
  185.   begin
  186.  
  187.    { get the new pattern from the pattern list }
  188.    GetIndPattern( currentPattern,sysPatListID,tempPatNum );
  189.    currentPatNum := tempPatNum;
  190.             
  191.    {force an update for this window}
  192.    InvalRect( thePort^.portRect );
  193.  
  194.   end; { if tempPatNum… }
  195.  
  196.  { set the pattern of the window }
  197.  PatRecHandle( WindowPeek( theWindow )^.refCon )^^.thePattern := currentPattern;
  198.  PatRecHandle( WindowPeek( theWindow )^.refCon )^^.number := currentPatNum;
  199. end;{DoInContent}
  200.  
  201. procedure DoMouseDown;
  202. {  Handle mouse-down events.  }
  203. var
  204.  whichWindow : WindowPtr; { window the mouse was pressed in }
  205.  thePart : INTEGER; { part of screen where mouse was pressed }
  206.  dragRect: Rect; { a window-sized rect for DragWindow }
  207.  growVal: longint; { new size of window after GrowWindow }
  208.  temp: Point;
  209.  
  210. begin
  211.  
  212.  { where on the screen was mouse pressed? }
  213.  thePart := FindWindow( theEvent.where, whichWindow );
  214.  
  215.  case thePart of
  216.   InDesk:      {Do nothing};
  217.   InMenuBar:   DoMenuClick;
  218.   InSysWindow:{Do nothing, cause there shouldn't be any};
  219.  
  220.   { if in top window then DoInContent, else make it the top window }
  221.   InContent: if whichWindow <> theWindow
  222.                                                         then SelectWindow( whichWindow )
  223.               else DoInContent;
  224.  
  225.   { if not in top window then make it the top window,
  226.     then do dragging }
  227.   InDrag:  begin
  228.             if whichWindow <> theWindow then SelectWindow( whichWindow );
  229.             dragRect := screenBits.bounds;
  230.             InsetRect( dragRect,4,4 );
  231.             DragWindow( whichWindow, theEvent.where, dragRect );
  232.            end;
  233.  
  234.   { if in grow box, resize window }
  235.   InGrow: begin
  236.            SetRect( dragRect, 20, 20, 512, 342 );
  237.            growVal := GrowWindow( whichWindow, theEvent.where, dragRect );
  238.  
  239.           { if non-zero, change the size of the window }
  240.           if ( growVal<>0 )
  241.           then
  242.            begin
  243.             SizeWindow( whichWindow, LoWord( growVal ), HiWord( growVal ), true );
  244.             InvalRect( thePort^.portRect );
  245.  
  246.             { erase the port to prepare for updating }
  247.                                              FillRect( thePort^.portRect, white );
  248.            end; { if ( growVal… }
  249.          end;
  250.  
  251.   { if on go-away box, track till they let go }
  252.   InGoAway: begin
  253.              if TrackGoAway( theWindow, theEvent.where )
  254.              then DestroyWindow( theWindow );
  255.             end;
  256.  end; {case}
  257.  
  258.  { make theWindow the current front window }
  259.  theWindow := FrontWindow;
  260.  
  261.  { if there's a window up, do a SetPort }
  262.  if FrontWindow <> NIL then SetPort( theWindow );
  263.  
  264. end; {DoMouseDown}
  265.  
  266. procedure DoUpdateEvent;
  267. { handle update events }
  268. var
  269.  whichWindow:WindowPtr; { target of update event }
  270.  r:rect;                { temporary rect for clipping }
  271.  
  272. begin
  273.  
  274.  { get the window to be updated }
  275.  whichWindow := WindowPtr( theEvent.message );
  276.  
  277.  { remember the current port before setting new port }
  278.  GetPort( oldPort );
  279.  SetPort( whichWindow );
  280.  
  281.  { make a rect as big as the grow box }
  282.  r := thePort^.portRect;
  283.  r.left := r.right - 15;
  284.  r.top := r.bottom - 15;
  285.  
  286.  { set the visRgn to a collection of the update regions }
  287.  BeginUpdate( whichWindow );
  288.  
  289.  { set the clip to the whole window,
  290.    and erase the grow box spot }
  291.  ClipRect( thePort^.portRect );
  292.     FillRect( r, white) ;
  293.  
  294.  { draw the oval using the pattern pointed
  295.    to by the window's refCon }
  296.  FillOval( thePort^.portRect,
  297.           PatRecHandle( WindowPeek( whichWindow )^.refCon )^^.thePattern );
  298.     FrameOval( thePort^.portRect );
  299.  
  300.  { draw the grow box, but only if this is the front window }
  301.  if FrontWindow = whichWindow
  302.  then
  303.   begin
  304.   { clip to a rect barely as big as the grow box }
  305.    ClipRect( r );
  306.  
  307.    DrawGrowIcon(whichWindow);
  308.  
  309.    { restore clip to be the whole window }
  310.    ClipRect( thePort^.portRect );
  311.   end;
  312.  
  313.  { restore the visRgn of the window }
  314.  EndUpdate( whichWindow );
  315.  
  316.  { restore original port }
  317.  SetPort( oldPort );
  318.  
  319. end; {DoUpdateEvt}
  320.  
  321. procedure DoActivateEvent;
  322. { handle activate and de-activate events }
  323. var 
  324.  targetWindow:WindowPtr; { window being affected }
  325.  r:rect;                 { temporary rect for clipping }
  326.  
  327. begin
  328.  
  329.  { get the window to be activated or de-activated }
  330.  targetWindow := WindowPtr( theEvent.message );
  331.  
  332.  { remember the current port before setting new port }
  333.  GetPort( oldPort );
  334.  SetPort( targetWindow );
  335.  
  336.  { make a rect just as big as the grow box }
  337.  r := thePort^.portRect;
  338.  r.left := r.right - 15;
  339.  r.top := r.bottom - 15;
  340.  
  341.  if Odd( theEvent.modifiers )
  342.  then { it's an activation }
  343.   begin
  344.  
  345.    { make it the top window }
  346.    SelectWindow( targetWindow );
  347.  
  348.    { clip and draw the grow box }
  349.    ClipRect( r );
  350.    DrawGrowIcon( targetWindow );
  351.  
  352.    { restore the clip to the whole window }
  353.    ClipRect( thePort^.portRect );
  354.   end
  355.  else { it's a de-activation }
  356.   begin
  357.  
  358.    { Force an update of this window. Only the area
  359.      occupied by the grow box will be updated }
  360.    InvalRect( r );
  361.  
  362.    { restore the port }
  363.    SetPort( oldPort ) ;
  364.  
  365.   end; { if Odd(… }
  366. end; {DoActivateEvent}
  367.  
  368. begin{main}
  369.  InitGraf( @ThePort );  { obligatory material goes here }
  370.  InitFonts;
  371.  InitWindows;
  372.  InitMenus;           { <-- boring initialization code }
  373.  TEInit;
  374.  InitDialogs( NIL );
  375.  InitCursor;
  376.  
  377.  { kick start the pop-up palette }
  378.  InitPatternPalette;
  379.  
  380.  { go put up some menus }
  381.  SetUpMenus;
  382.  
  383.  { load the system pattern list }
  384.  systemPatterns := PatHandle( GetResource( 'PAT#', sysPatListID ) );
  385.  
  386.  currentPatNum := 1;
  387.  { start currentPattern at black (pattern #1) }
  388.  GetIndPattern( currentPattern, sysPatListID, 1 );
  389.  
  390.  { start window placement at 20,20 }
  391.  SetPt( nextWindow, 20, 20 );
  392.  
  393.  { put up the first window, and make it 'theWindow' }
  394.  MakeNewWindow;
  395.  theWindow := FrontWindow;
  396.  
  397.  { this gets set to true when Quit command is selected }
  398.  programDone := false;
  399.  
  400.  { here's the main event loop }
  401.  repeat
  402.  if GetNextEvent( everyEvent, theEvent ) then
  403.   case theEvent.what of
  404.    MouseDown:    DoMouseDown;
  405.    UpdateEvt:    DoUpdateEvent;
  406.    ActivateEvt:  DoActivateEvent;
  407.  
  408.    { if you're not handling an event,
  409.      let the system have some time }
  410.    otherwise  SystemTask;
  411.  
  412.   end; {case}
  413.  until programDone;
  414.  
  415.     { now let's dispose of any windows still up }
  416.     while FrontWindow <> NIL do
  417.         DestroyWindow( FrontWindow );
  418.  
  419. end.
  420.